﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Input;
using System.Windows.Media;
using System.Runtime.Serialization.Json;
using MSSClient.Model;
using System.Runtime.Serialization.Formatters.Binary;
using System.Diagnostics;
using System.Xml;
using MSSClient.Utils;
using System.Runtime.InteropServices;
using mhc.CMessageBox;
using Zmy.Wpf.CMessageBox;

namespace MSSClient
{
    

    /// <summary>
    /// 启动入口
    /// </summary>
    public partial class Login : Window
    {
        //防止程序运行多个实例的方法有多种,如:通过使用互斥量和进程名等.而我想要实现的是:在程序运行多个实例时激活的是第一个实例,使其获得焦点,并在前端显示.
        //主要用到两个API 函数:
        //ShowWindowAsync 该函数设置由不同线程产生的窗口的显示状态。 
        //SetForegroundWindow 该函数将创建指定窗口的线程设置到前台，并且激活该窗口。键盘输入转向该窗口，并为用户改各种可视的记号。系统给创建前台窗口的线程分配的权限稍高于其他线程。

        /// <summary> 
        /// 该函数设置由不同线程产生的窗口的显示状态。 
        /// </summary> 
        /// <param name="hWnd">窗口句柄</param> 
        /// <param name="cmdShow">指定窗口如何显示。查看允许值列表，请查阅ShowWlndow函数的说明部分。</param> 
        /// <returns>如果函数原来可见，返回值为非零；如果函数原来被隐藏，返回值为零。</returns> 
        [DllImport("User32.dll")]
        private static extern bool ShowWindowAsync(IntPtr hWnd, int cmdShow);
        /// <summary> 
        /// 该函数将创建指定窗口的线程设置到前台，并且激活该窗口。键盘输入转向该窗口，并为用户改各种可视的记号。系统给创建前台窗口的线程分配的权限稍高于其他线程。 
        /// </summary> 
        /// <param name="hWnd">将被激活并被调入前台的窗口句柄。</param> 
        /// <returns>如果窗口设入了前台，返回值为非零；如果窗口未被设入前台，返回值为零。</returns> 
        [DllImport("User32.dll")]
        private static extern bool SetForegroundWindow(IntPtr hWnd);
        private const int WS_SHOWNORMAL = 1;

        Dictionary<string, LoginData> users;
        String lastUserName;
        String strResultR;
       ListModel listModle = new ListModel();
        private List<BackgroundWorker> threadPool = new List<BackgroundWorker>();

        public Login()
        {
            try
            {
                #region
                this.DataContext = listModle;

                //判断是否存在已经打开的客户端，有的话就定位显示在最前面
                Process tProcess = CommonUtil.RunningInstance();
                if (null != tProcess)
                {
                    File.Delete("C:\\openClient.txt");//删除标识文件
                    ShowWindowAsync(tProcess.MainWindowHandle, WS_SHOWNORMAL); //显示客户端
                    SetForegroundWindow(tProcess.MainWindowHandle);            //显示客户端在最前面
                    //MessageBox.Show("程序已经在运行中，不允许重复多次运行！", "提示");
                    Process.GetCurrentProcess().Kill();
                }

                InitializeComponent();//初始化界面
                readUserInfo();//读取缓存信息
                lastUserName = username.Text;

                //获取当前程序版本
                var versionNum = System.Reflection.Assembly.GetExecutingAssembly().GetName().Version;
                version.Content = "当前版本：" + versionNum.ToString();
                password.TextDecorations = new TextDecorationCollection(new TextDecoration[] 
                {
                    new TextDecoration()
                    {
                        Location = TextDecorationLocation.Strikethrough,
                        Pen = new Pen(Brushes.Black, 10f)
                        {
                            DashCap =  PenLineCap.Round,
                            StartLineCap= PenLineCap.Round,
                            EndLineCap= PenLineCap.Round,
                            DashStyle= new DashStyle(new double[] {0.0,1.2 }, 0.6f)
                        }
                    }
                });

                // 判断是否是从web启动
                string openStr = openClientFromWeb();
                if (openStr.Equals("no"))
                {
                    //如果不是web启动，不执行任何操作 
                }
                else
                {
                    String[] username_password = openStr.Split(',');//读取标识文件数据：用户名，密码
                    string username1 = username_password[0];
                    string password1 = username_password[1];
                    File.Delete("C:\\openClient.txt");//删除标识文件
                    username.Text = username1;
                    loginFun(username1.Trim(), password1.Trim());
                }
            }
            catch (Exception ex)
            {
                CommonUtil.WriteLog(ex);
            }
            #endregion
        }


        //登录
        private void login_Click(object sender, RoutedEventArgs e)
        {
            loginFun(username.Text.Trim(), password.Text);
        }

        //读取指定文件，判断是否是web端要求启动
        public string openClientFromWeb() 
        {
            string path = "C:\\openClient.txt";
            if (!File.Exists(path))
                return "no";
            else
            {
                string txtStr = File.ReadAllText(path, Encoding.Default);
                return txtStr;
            }
        }

        /// <summary>
        /// 执行登录逻辑
        /// </summary>
        /// <param name="username"></param>
        /// <param name="password"></param>
        public void loginFun(string username,string password)
        {
            #region
            //changSiteBtn.IsEnabled = false;
            login.IsEnabled = false;
            login_name.Content = "登录中...";
            Dictionary<string, string> paramsDic = new Dictionary<string, string>();
            paramsDic.Add("account", username);
            paramsDic.Add("password", password);
            if (username == "" || null == username)
            {
                //MessageBox.Show("用户名不能为空", "登陆提示");
                CommonUtil.ShowMsgFrom("用户名不能为空");
                changeBottonStyle();
                return;
            }
            if (password == "" || null == password)
            {
                CommonUtil.ShowMsgFrom("密码不能为空");
                //MessageBox.Show("密码不能为空", "登陆提示");
                changeBottonStyle();
                return;
            }
            LoginData model = null;
            BackgroundWorker worker = new BackgroundWorker();
            bool updateTag = false;
            worker.DoWork += (o, a) =>
            {
                String strResult = CommonUtil.LoginPost(Global.getInstance().strUrl + Global.getInstance().strLogin, paramsDic);
                strResultR = strResult;
                if (strResultR.Equals(""))
                {
                    CommonUtil.ShowMsgFrom("网络好像出了点问题，请查看网络是否正常！");
                    //MessageBox.Show("网络好像出了点问题，请查看网络是否正常！", "提示信息");
                    changeBottonStyle();
                    return;
                }
                if (strResultR.Equals("urlError"))
                {
                    CommonUtil.ShowMsgFrom("服务器地址有误，请检查！");
                    //MessageBox.Show("服务器地址有误，请检查！", "提示信息");
                    changeBottonStyle();
                    return;
                }
                if (strResultR.Equals("netError"))
                {
                    CommonUtil.ShowMsgFrom("服务器好像出了点问题，请联系管理员！");
                    //MessageBox.Show("服务器好像出了点问题，请联系管理员！", "提示信息");
                    changeBottonStyle();
                    return;
                }

                var ms = new MemoryStream(Encoding.UTF8.GetBytes(strResult));
                {
                    DataContractJsonSerializer deseralizer = new DataContractJsonSerializer(typeof(LoginData));
                    model = (LoginData)deseralizer.ReadObject(ms);// //反序列化ReadObject
                }

                if (null == model)
                {
                    CommonUtil.ShowMsgFrom("登录失败，服务器数据没有返回！,请稍后重试");
                    //MessageBox.Show("登录失败，服务器数据没有返回！,请稍后重试", "提示消息");
                    changeBottonStyle();
                    return;
                }
                //登录失败提示消息
                if (model.code.Equals("Fail"))
                {
                    CMessageBox.Show(model.message, "信息提示", CMessageBoxButton.OKCancel, CMessageBoxImage.None, CMessageBoxDefaultButton.OK);
                    changeBottonStyle();
                    return;
                }
                //登录失败提示消息
                if (model.code.Equals("Error"))
                {
                    CMessageBox.Show(model.message, "信息提示", CMessageBoxButton.OKCancel, CMessageBoxImage.None, CMessageBoxDefaultButton.OK);
                    changeBottonStyle();
                    return;
                }
                Global.getInstance().loginData = model;
                Global.getInstance().getOCRTrigger = CommonUtil.getSysProperty("OCR_Trigger");
                Global.getInstance().sysTypeCode = CommonUtil.getSysTypeCode();

                if (null == model) return;
                if (model.code.Equals("Fail")) return;
                if (model.code.Equals("Error")) return;
                if (strResultR.Equals("urlError")) return;
                if (strResultR.Equals("netError")) return;
                if (strResultR.Equals("")) return;
                //保存用户名密码缓存
                saveUserInfo(lastUserName);

                //获取数据库系统版本号，用来和现在的系统版本比较，不同则更新版本
                
                //获取当前系统版本号
                var versionv = System.Reflection.Assembly.GetExecutingAssembly().GetName().Version;
                
                UpGradeModel versionModel = CommonUtil.getSysProperty("New_Version");
                //比较版本号
                if (null != versionModel && versionModel.value != versionv.ToString())
                {
                    String message = "有新版本，是否下载更新。\n\n" + "版本号：" + versionModel.value + "\n" + "更新时间：" + versionModel.updateDate + "\n" + "更新内容：" + versionModel.description;
                    CMessageBoxResult cmr = CMessageBox.UpgradeShow( message, "更新提示", CMessageBoxButton.OKCancel, CMessageBoxImage.None, CMessageBoxDefaultButton.OK);
                    if (cmr.Equals(CMessageBoxResult.OK) || cmr.Equals(CMessageBoxResult.None))
                    {
                        updateTag = true;
                    }
                    if (updateTag)
                    {
                        App.Current.Dispatcher.Invoke((Action)(() =>
                        {
                            UpgradeClientDlg upgradeClientDlg = new UpgradeClientDlg();
                            upgradeClientDlg.Show();
                            upgradeClientDlg.ShowActivated = true;
                            this.Close();
                        }));
                    }
                }
            };
            worker.RunWorkerCompleted += (o, a) =>
            {
                if (updateTag)
                {
                    this.Close();
                    return;
                }
                    
                //打开主页面
                if (null != model && model.code.Equals("Success"))
                {
                    MSSWindow winObj = new MSSWindow();
                    winObj.username.Content = model.data.name + "(" + username + ")";
                    winObj.userNameCN.Content = username;
                    winObj.loginData = model;
                    winObj.Show();
                    winObj.ShowActivated = true;
                    CommonUtil.ShowMsgFrom("用户：[" + username + "]登录成功");
                    this.Close();
                }
            };
            worker.RunWorkerAsync();
        #endregion
        }

        //把按钮状态还原
        public void changeBottonStyle()
        {
            login_name.Dispatcher.Invoke(new Action(() =>
            {
                login_name.Content = "登 录";
            }));

            login.Dispatcher.Invoke(new Action(() =>
            {
                login.IsEnabled = true;
            }));
        }

        /*
         * 保存用户名密码到缓存
         * 逻辑：保存20个用户(暂不实现)
         * 目前只记录一个
         */
        public void saveUserInfo(String lastUserName)
        {
            #region
            LoginData user = new LoginData();
            List<LoginData> tempList = new List<LoginData>();
            // 登录时 如果没有Data.bin文件就创建、有就打开
            string filePath = @"C:\MssClientCache\";//缓存保存地址
            if (!Directory.Exists(filePath))//判断文件夹是否存在 
            {
                Directory.CreateDirectory(filePath);//不存在则创建文件夹 
            }
            FileStream fs = new FileStream(filePath + "userData.bin", FileMode.OpenOrCreate);
            BinaryFormatter bf = new BinaryFormatter();
            Dictionary<string, LoginData> dic = new Dictionary<string, LoginData>();
            if (fs.Length > 0)
            {
                //读取原来的保存的数据
                dic = bf.Deserialize(fs) as Dictionary<string, LoginData>;
            }

            //超过20条则只获取后面20条的数据
            if (dic.Count >= 20)
            {
                int count = 1;
                for (int i = dic.Values.Count-1; i>=0;i--)
                {
                    tempList.Add(dic.Values.ElementAt(i));
                    count++;
                    if (count == 20) break;//超过指定的保存数量，跳出
                }
            }
            else
            {
                foreach (LoginData group in dic.Values)
                {
                    tempList.Add(group);
                }
                tempList.Reverse();
            }

            // 保存在实体类属性中
            username.Dispatcher.Invoke(new Action(() =>
            {
                user.LoginName = username.Text.Trim();
            }));
            bool check = true;
            remember_checkBox.Dispatcher.Invoke(new Action(() =>
            {
                check = (bool)remember_checkBox.IsChecked;
            }));

            if (check)
            {
                //保存密码，选中状态
                password.Dispatcher.Invoke(new Action(() =>
                {
                    user.Pwd = password.Text.Trim();
                }));
            }
            
            foreach (LoginData ld in tempList)
            {
                string usernameStr = "";
                username.Dispatcher.Invoke(new Action(() =>
                {
                    usernameStr = username.Text.Trim();
                }));
                
                //如果缓存中已经存在这个用户key，则先去掉
                if (ld.LoginName.Equals(usernameStr))
                {
                    tempList.Remove(ld);
                    break;
                }
            }
            //在前面插入本次的登录缓存
            tempList.Insert(0, user);
            dic.Clear();//清空，重新赋值
            foreach (LoginData ld in tempList)
            {
                dic.Add(ld.LoginName, ld);
            }
            //添加用户信息到集合

            fs.Close();
            FileStream fsNew = new FileStream(filePath + "userData.bin", FileMode.Create);
            //写入文件
            bf.Serialize(fsNew, dic);
            //关闭
            fsNew.Close();
            #endregion
        }

        //读取用户缓存信息-用户名，密码
        public List<LoginData> userList = new List<LoginData>();
        public void readUserInfo()
        {
            #region
            //读取文件流对象
            string filePath = "C:/MssClientCache/";//缓存保存地址
            
            if (!Directory.Exists(filePath))//判断文件夹是否存在 
            {
                return;//不存在就不执行下面
            }
            FileStream fs = new FileStream("C:/MssClientCache/userData.bin", FileMode.OpenOrCreate);
            if (fs.Length > 0)
            {
                BinaryFormatter bf = new BinaryFormatter();
                //读出存在Data.bin 里的用户信息
                users = bf.Deserialize(fs) as Dictionary<string, LoginData>;

                //循环添加到Combox1
                foreach (LoginData user in users.Values)
                {
                    userList.Add(user);
                }
                username.Text = userList[0].LoginName;
                DisplayUserInfo();
                //combox1 用户名默认选中第一个
                //if (username.Items.Count > 0)
                //    username.SelectedIndex = username.Items.Count - 1;
            }
            fs.Close();
            #endregion
        }

        //显示用户所对应匹配的信息
        private void DisplayUserInfo()
        {
            string key = username.Text.Trim();
            //查找用户Id
            if (users.ContainsKey(key) == false)
            {
                password.Text = "";
                return;
            }
            //查找到赋值
            LoginData user = users[key];
            password.Text = user.Pwd;
            // 如有密码 选中复选框
            remember_checkBox.IsChecked = password.Text.Trim().Length > 0 ? true : false;
        }

        /// <summary>
        /// 更换地址-生产屏蔽
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void changeSite_Click(object sender, RoutedEventArgs e)
        {
            #region
            string configPath = System.AppDomain.CurrentDomain.BaseDirectory;
            string old_site = "";
            XmlDocument MyXml = new XmlDocument();
            MyXml.Load(configPath + "MSSClient.exe.config");
            //获取<configuration>节点的所有子节点
            XmlNodeList MyNodeList = MyXml.SelectSingleNode("configuration").ChildNodes;

            //遍历<configuration>下的所有子节点
            foreach (XmlNode MyNode in MyNodeList)
            {
                if (MyNode.Name == "appSettings")
                {
                    XmlNodeList InfoPageNodeList = MyNode.ChildNodes;
                    //遍历InfoPage节点
                    foreach (XmlNode InfoPageNode in InfoPageNodeList)
                    {
                        if (InfoPageNode.Attributes["key"].InnerXml == "strUrl")
                        {
                            old_site = InfoPageNode.Attributes["value"].InnerXml;
                            break;
                        }
                    }
                    break;
                }
            }
            ChangeWebSiteDlg dlg = new ChangeWebSiteDlg(old_site);
            dlg.Show();//显示修改弹窗
            dlg.changeWebSiteDlg += () =>
            {
                //此步骤关闭登录窗口重新打开的用意在于：让Global重新读取数据
                this.Close();
                Process p = Process.Start(configPath+"MSSClient.exe");
            };
            #endregion
        }

        private void item_SelectionChanged(object sender, SelectionChangedEventArgs e)
        {
            this.listModle.PopupIsOpen = false;
            var data = (sender as ListBox).SelectedItem as Content;
            if (data == null)
            {
                this.listModle.PopupIsOpen = false;
                return;
            }
            username.Text = data.Name;
            password.Text = data.Password;
            remember_checkBox.IsChecked = password.Text.Length > 0 ? true : false;
            this.listModle.Names.Clear();
        }

        private void popupContent_Closed(object sender, EventArgs e)
        {
            this.listModle.Names.Clear();
        }

        /// <summary>
        /// 在此增加内容
        /// </summary>
        private void InitialSetValue()
        {
            this.Dispatcher.BeginInvoke(new Action(() =>
            {
                //userList.Reverse();
                if (userList.Count!=0)
                {
                    this.listModle.Names.Clear();
                    foreach (LoginData ld in userList)
                    {
                        Content content = new Content();
                        content.Name = ld.LoginName;
                        content.Password = ld.Pwd;
                        this.listModle.Names.Add(content);
                    }
                }
            }));
        }

        private void username_MouseDoubleClick(object sender, MouseButtonEventArgs e)
        {
            #region
            if (this.listModle.PopupIsOpen)
                this.listModle.PopupIsOpen = false;
            else
                this.listModle.PopupIsOpen = true;

            if (threadPool.Count > 0)
            {
                threadPool[0].CancelAsync();
            }

            threadPool.Clear();

            string key = this.username.Text.Trim();

            BackgroundWorker worker = new BackgroundWorker();

            worker.WorkerReportsProgress = true;

            worker.WorkerSupportsCancellation = true;

            worker.DoWork += (o, p) =>
            {
                InitialSetValue();

                p.Result = this.listModle.Names;
            };

            worker.RunWorkerCompleted += (o, p) =>
            {
                //this.listModle.Names = p.Result as ObservableCollection<Content>;

                //if (this.listModle.Names.Count <= 0)
                //{
                //    this.listModle.PopupIsOpen = false;
                //}
            };

            threadPool.Add(worker);

            Thread.Sleep(100);

            if (threadPool.Count > 0)
            {
                threadPool[0].RunWorkerAsync();
            }
            #endregion
        }

        private void username_TextChanged(object sender, TextChangedEventArgs e)
        {
            this.listModle.Names.Clear();
            this.listModle.PopupIsOpen = false;
        }

        private void tipBtn_Click(object sender, RoutedEventArgs e)
        {
            MessageBox.Show("1、双击用户名输入框可以显示最近登录过的用户名缓存 " +
                            "\n2、登陆后双击当前用户名可以快速复制用户信息 \n", 
                            "小贴士（2条）");
        }

    }
}
